import { createMachine, assign } from 'xstate';

function invokeFetchSubreddit(context) {
  const { subreddit } = context;

  return fetch(`https://www.reddit.com/r/${subreddit}.json`)
          .then(res => res.json())
          .then(json => json.data.children.map((child) => child.data));
}

// MARK: 1、创建状态机
export const redditMachine = createMachine({
  id: 'reddit',
  /** 初始状态 -> 空闲 */
  initial: 'idle',
  /** 上下文对象，用来储存实时数据 */
  context: {
    /** 已选子贴 */
    subreddit: null, // none selected
    /** 子贴的具体信息 */
    posts: null,
  },
  /** 
   * 这里要枚举出 states 所有可能的状态值：idle 和 selected
   */
  states: {
    /** 空闲 -> 还没有子贴被选中 */
    idle: {},
    /** 已选 -> 某个子贴被选中 */
    selected: {
      // 子状态 -> 子贴内容的加载状态：loading、loaded、failed
      initial: 'loading',
      states: {
        loading: {
          // 当 state 变成 loading 时触发此方法
          invoke: {
            id: "fetch-subreddit",
            // invoke 触发的具体事件
            src: invokeFetchSubreddit,
            // 事件处理成功后执行 onDone 的内容
            onDone: {
              // 状态置为 loaded
              target: 'loaded',
              // 将事件数据合并到 posts 中
              actions: assign({
                posts: (context, event) => event.data
              })
            },
            // 事件处理失败后将状态置为 failed
            onError: "failed",
          }
        },
        // 因为是有限状态机，所以必须在 states 中显式声明出所有可能的状态值
        loaded: {},
        failed: {}
      }
    }
  },
  on: {
    SELECT: {
      // 过渡 transition 去子状态 '.selected' (注意 select 前面的点儿, 它代表一个关联目标 (relative-targets)
      target: '.selected',
      // 指派 assign event.name 给 context.subreddit
      actions: assign({
        subreddit: (context, event) => event.name
      })
    }
  }
});

// 创建一个顶层（top-level）过渡（transition），每当用户选择子贴后，触发该过渡。
const selectEvent = {
  type: 'SELECT', // event type
  name: 'reactjs' // subreddit name
};
